"""
静态HTML生成器
用于将文章内容填充到模板中生成静态HTML文件
"""
import os
import re
import uuid
from datetime import datetime
from jinja2 import Environment, FileSystemLoader
from flask import current_app
import markdown


class StaticHTMLGenerator:
    """静态HTML生成器"""
    
    def __init__(self):
        self.template_dir = None
        self.static_dir = None
        self.jinja_env = None
        self._initialized = False
    
    def _ensure_initialized(self):
        """确保初始化完成"""
        if not self._initialized:
            self.template_dir = os.path.join(current_app.root_path, 'templates')
            self.static_dir = os.path.join(current_app.root_path, 'static', 'html')
            self.ensure_static_dir()
            
            # 初始化Jinja2环境
            self.jinja_env = Environment(
                loader=FileSystemLoader(self.template_dir),
                autoescape=True
            )
            self._initialized = True
    
    def ensure_static_dir(self):
        """确保静态HTML目录存在"""
        if not os.path.exists(self.static_dir):
            os.makedirs(self.static_dir, exist_ok=True)
    
    def generate_post_html(self, post):
        """
        生成文章静态HTML文件
        
        Args:
            post: 文章对象
            
        Returns:
            str: 生成的HTML文件路径
        """
        self._ensure_initialized()
        try:
            # 创建按年月日分组的目录结构，使用html子目录避免与Flask静态路由冲突
            post_date = post.published_at or post.created_at
            year_month_day = post_date.strftime('%Y/%m/%d')
            post_dir = os.path.join(self.static_dir, year_month_day)
            os.makedirs(post_dir, exist_ok=True)
            
            # 生成文件名：使用UUID命名
            unique_id = str(uuid.uuid4())
            html_filename = f"{unique_id}.html"
            html_path = os.path.join(post_dir, html_filename)
            
            # 渲染Markdown内容
            md = markdown.Markdown(extensions=['codehilite', 'fenced_code', 'tables', 'toc'])
            rendered_content = md.convert(post.content)
            
            # 准备模板数据
            template_data = {
                'post': post,
                'title': post.title,
                'description': post.excerpt or post.content[:200] + '...' if len(post.content) > 200 else post.content,
                'keywords': ', '.join([tag.name for tag in post.tags]) if post.tags else '',
                'author': post.author.name or post.author.username,
                'published_at': post.published_at or post.created_at,
                'view_count': post.view_count or 0,  # 使用实际的统计数据
                'like_count': post.like_count or 0,   # 使用实际的统计数据
                'comment_count': post.comment_count or 0, # 使用实际的统计数据
                'category': post.category,
                'tags': post.tags,
                'cover_image': post.cover_image,
                'content': rendered_content,  # 使用渲染后的HTML内容
                'excerpt': post.excerpt,
                'generated_at': datetime.now()
            }
            
            
            # 渲染HTML模板
            html_content = self._render_post_template(template_data)
            
            # 保存HTML文件
            with open(html_path, 'w', encoding='utf-8') as f:
                f.write(html_content)
            
            # 更新数据库中的html_path字段
            from extensions import db
            relative_path = os.path.relpath(html_path, current_app.root_path).replace('\\', '/')
            post.html_path = '/' + relative_path  # 确保路径以 / 开头
            db.session.commit()
            
            # 返回绝对路径（用于数据库存储）
            relative_path = os.path.relpath(html_path, current_app.root_path)
            return '/' + relative_path.replace('\\', '/')  # 确保路径以 / 开头
            
        except Exception as e:
            current_app.logger.error(f"生成静态HTML失败: {str(e)}")
            raise
    
    def _render_post_template(self, data):
        """渲染文章模板"""
        from flask import url_for
        
        # 创建一个模拟的url_for函数，返回硬编码的URL
        def mock_url_for(endpoint, **values):
            if endpoint == 'main.index':
                return '/'
            elif endpoint == 'main.about':
                return '/about'
            elif endpoint == 'main.contact':
                return '/contact'
            elif endpoint == 'main.search':
                return '/search'
            elif endpoint == 'static':
                # 处理静态资源路径
                filename = values.get('filename', '')
                return f'/static/{filename}'
            else:
                return '#'
        
        # 创建模拟的current_user对象
        class MockUser:
            is_authenticated = False
            
        # 添加模拟的url_for函数和current_user到模板上下文
        data['url_for'] = mock_url_for
        data['current_user'] = MockUser()
        
        template = self.jinja_env.get_template('post.html')
        return template.render(**data)
    
    def _sanitize_filename(self, filename):
        """清理文件名，移除非法字符"""
        # 移除或替换非法字符
        filename = re.sub(r'[<>:"/\\|?*]', '_', filename)
        # 移除多余的空格和点
        filename = re.sub(r'\s+', '_', filename.strip())
        filename = filename.strip('.')
        return filename
    
    def delete_post_html(self, html_path):
        """
        删除文章的静态HTML文件
        
        Args:
            html_path: HTML文件路径
        """
        self._ensure_initialized()
        try:
            if html_path:
                full_path = os.path.join(current_app.root_path, html_path)
                if os.path.exists(full_path):
                    os.remove(full_path)
                    current_app.logger.info(f"删除静态HTML文件: {html_path}")
        except Exception as e:
            current_app.logger.error(f"删除静态HTML文件失败: {str(e)}")
    
    def update_post_html(self, post):
        """
        更新文章的静态HTML文件
        
        Args:
            post: 文章对象
            
        Returns:
            str: 更新后的HTML文件路径
        """
        self._ensure_initialized()
        # 先删除旧文件
        if post.html_path:
            self.delete_post_html(post.html_path)
        
        # 生成新文件
        return self.generate_post_html(post)


# 创建全局实例
html_generator = StaticHTMLGenerator()
